<template>
	<view>
		<view class="fileWrap">
			<view ref="fileView" class="hFile" @click="chooseFile">
				<!-- 自定义上传组件样式 -->
				<slot name="upload">
					<view class="upload-bg">
						<uni-icons type="cloud-upload" size="36"></uni-icons>
						<text>{{uploadText}}</text>
					</view>
				</slot>
			</view>
		</view>
		<view v-if="showTable">
			<!-- sheet -->
			<view class="sheet">
				<view class="tab" :class="index == sheetIndex ?'tab-selected':'' " v-for="(item,index) in sheets"
					:key="index" @click="selectSheet(index)">
					{{item.name}}
				</view>
			</view>
			<!-- 表结构 -->
			<uni-table ref="table" border stripe emptyText="暂无更多数据"><!-- type="selection" -->
				<!-- 表头行 -->
				<uni-tr>
					<uni-th align="center" v-for="(item,index) in tableTitles" :key="'th'+index">{{item}}</uni-th>
				</uni-tr>

				<!-- 表格数据行 -->
				<uni-tr v-for="(item,index) in tableList" :key="'tr'+index">
					<uni-td align="center" v-for="(items,i) in item" :key="'td'+i">{{items}}</uni-td>
				</uni-tr>

			</uni-table>
		</view>
	</view>
</template>
<script>
	import {
		appFile
	} from './appFile.js'
	import * as XLSX from 'xlsx';
	import {
		nextTick
	} from "vue";
	import { baseURL } from '@/utils/request/index.js'
	/**
	 * 
	 */
	export default {
		props: {
			uploadText: {
				type: String,
				default: '本地文件选择'
			},
			// webviewID需唯一，不同窗口也不要同Id
			childId: {
				type: String,
				default: 'qyUpload'
			},
			// 文件大小上限 M
			size: {
				type: Number,
				default: 10
			},
			// nvue不支持跟随窗口滚动
			position: {
				type: String,
				// #ifdef APP-NVUE
				default: 'absolute',
				// #endif
				// #ifndef APP-NVUE
				default: 'static',
				// #endif
			},
			// top,left,bottom,right仅position=absolute时才需要传入
			top: {
				type: [String, Number],
				default: ''
			},
			left: {
				type: [String, Number],
				default: ''
			},
			bottom: {
				type: [String, Number],
				default: ''
			},
			right: {
				type: [String, Number],
				default: ''
			},
			// 上传接口参数设置
			option: {
				type: Object,
				default: () => {
					return {
						url: '',
						name: 'file',
						header: {},
						formData: {}
					}
				}
			},
			formData: {
				type: Object,
				default: () => {
					return {}
				}
			}
		},
		data() {
			return {
				// 本地文件路径
				filePath: '',
				// 文件名
				fileName: '',
				// table表状态
				showTable: false,
				// 表数据
				workbookData: {},
				// sheet列表
				sheets: [],
				// 选中索引
				sheetIndex: 0,
				// 表格表头
				tableTitles: [],
				// 表格数据
				tableList: [],
				// app 文件对象
				appFile: null,
				// 文件选择触发面宽度
				width: '100%',
				// 文件选择触发面高度
				height: '80px',
				// 文件上限 为了正常显示只能传一个文件
				count: 1,


			}
		},
		watch: {
			option(v) {
				// #ifdef APP-PLUS
				this.appFile && this.show();
				// #endif

			}
		},
		updated() {
			// #ifdef APP-PLUS
			if (this.isShow) {
				this.appFile && this.show();
			}
			// #endif
		},
		mounted() {
			// #ifdef APP-PLUS
			console.log("开始装载")

			let dates = new Date().getTime()
			let folder = 'qyFile_' + dates;

			this.option.formData = {
				name: folder,
			};

			this._size = 0;
			let WEBID = this.childId + new Date().getTime();
			this.appFile = new appFile({
				id: WEBID,
				width: this.width,
				height: this.height,
				option: this.option,
				debug: false,
				instantly: true,
				prohibited: {
					// 大小
					size: this.size,
					// 允许上传的格式
					formats: 'xls,xlsx',
					// 限制选择的格式
					accept: 'file',
					count: this.count,
					// 是否多选
					multiple: false,
				},
				onchange: this.onchange,
				onprogress: this.onprogress,
			});
			this.create();
			// #endif
			// 需判断是否当前页显示
			uni.$on('fileListShow', this.show);
		},
		beforeDestroy() {
			uni.$off('fileListShow', this.show);
			// #ifdef APP-PLUS
			this.appFile.dom.close();
			// #endif
		},
		methods: {

			/**
			 * @returns {Map} 已选择的文件Map集
			 */
			onchange(files) {
				this.$emit('change', files);
				this._size = files.size;
				return files.size >= this.count ? this.hide() : this.show();
			},
			/**
			 * @returns {object} 当前上传中的对象
			 */
			onprogress(item, end = false) {
				console.log("文件接收")
				let that = this;
				if (end) {
					setTimeout(() => {
						console.log(item)
						this.filePath = item.path
						this.fileName = item.name.split('.')[0]

						const workbook = XLSX.read(item.data, {
							type: "binary",
							cellText: false,
							cellDates: true,
						});
						that.workbookData = workbook;
						that.sheets = workbook.Workbook.Sheets;
						that.selectSheet(0)

					}, 0)

				}
			},
			// 创建选择器
			create() {
				console.log("开始创建选择器")
				// 若iOS端服务端处理不了跨域就将hybrid目录内的html放到服务端去，并将此处path改成服务器上的地址
				let path = '/uni_modules/qy-excel-preview/hybrid/html/uploadFile.html';
				let dom = this.appFile.create(path);
				dom.setStyle({
					position: this.position
				});
				dom.loadURL(path);
				setTimeout(() => {
					// #ifdef APP-NVUE
					plus.webview.currentWebview().append(dom);
					// #endif
					// #ifndef APP-NVUE
					this.$root.$scope.$getAppWebview().append(dom);
					// #endif
					this.show();
				}, 300)
			},
			show() {
				console.log("打开了页面")
				if (this._size && (this._size >= this.count)) {
					return;
				}
				this.isShow = true;
				this.appFile && this.getDomStyles(styles => {
					this.appFile.dom.setStyle(styles)
				});
			},
			getDomStyles(callback) {
				// #ifndef APP-NVUE
				let view = uni
					.createSelectorQuery()
					.in(this)
					.select('.fileWrap')
				view.fields({
						size: true,
						rect: true
					},
					({
						height,
						width,
						top,
						left,
						right,
						bottom
					}) => {
						uni.createSelectorQuery()
							.selectViewport()
							.scrollOffset(({
								scrollTop
							}) => {
								return callback({
									top: parseInt(top) + parseInt(scrollTop) + 'px',
									left: parseInt(left) + 'px',
									width: parseInt(width) + 'px',
									height: parseInt(height) + 'px'
								})
							})
							.exec()
					}
				).exec()
				// #endif
				// #ifdef APP-NVUE
				const dom = weex.requireModule('dom')
				dom.getComponentRect(this.$refs.fileView, ({
					size: {
						height,
						width,
						top,
						left,
						right,
						bottom
					}
				}) => {
					return callback({
						top: parseInt(top) + 'px',
						left: parseInt(left) + 'px',
						width: parseInt(width) + 'px',
						height: parseInt(height) + 'px',
						right: parseInt(right) + 'px',
						bottom: parseInt(bottom) + 'px'
					})
				})
				// #endif
			},
			hide() {
				this.isShow = false;
				// #ifdef APP-PLUS
				this.appFile && this.appFile.dom.setStyle({
					top: '-100px',
					left: '0px',
					width: '1px',
					height: '100px',
				});
				// #endif
				// #ifdef H5
				this.appFile.dom.style.display = 'none'
				// #endif
			},
			// 选择文件
			chooseFile() {
				let that = this;
				// #ifdef MP-WEIXIN
				// 如果是微信小程序，从聊天记录选择文件
				wx.chooseMessageFile({
					count: 1,
					type: "file",
					extension: ['xls', 'xlsx'],
					success(res) {
						this.filePath = res.tempFiles[0].path
						this.fileName = res.tempFiles[0].name.split('.')[0]
						// 获取文件信息流
						var FileSystemManager = wx.getFileSystemManager();
						FileSystemManager.readFile({
							filePath: res.tempFiles[0].path,
							encoding: 'base64',
							success(data) {
								// 解析excel信息流
								const workbook = XLSX.read(data.data, {
									type: "base64",
									cellText: false,
									cellDates: true,
								});

								that.workbookData = workbook;
								that.sheets = workbook.Workbook.Sheets;

								that.selectSheet(0)
							},
							fail(err) {
								console.log('fail', err)
							}
						})
					}
				})
				// #endif
				// #ifdef H5
				uni.chooseFile({
					count: 1, //默认100
					extension: ['.xls', '.xlsx'],
					success: (res) => {
						this.filePath = res.tempFiles[0].path
						this.fileName = res.tempFiles[0].name.split('.')[0]
						const token = uni.getStorageSync('tokenInfo');
						uni.showLoading({
							title: 'Excel上传中...'
						})
						// 上传文件
						const uploadTask = uni.uploadFile({
						  url: baseURL + 'y/tbdj/importData', // 你的上传API地址
						  filePath: this.filePath,
						  name: 'file', // 这里根据API的要求来定义
						  formData: this.formData,
						  header: {
							  [token.tokenName]: token.tokenValue
						  },
						  success: uploadResult => {
							  const relust = JSON.parse(uploadResult.data);
							  if (relust.code == "0") {
								  uni.showToast({
								  	title: relust.data
								  })
							  } else {
								  uni.showToast({
								  	title: relust.msg,
									icon: 'none'
								  })
							  }
							// 上传成功处理逻辑
							console.log('upload success:', uploadResult);
						  },
						  fail: uploadError => {
							  uni.showToast({
							  	title: 'Excel数据上传失败！'
							  })
							// 上传失败处理逻辑
							console.log('upload fail:', uploadError);
						  }
						});
						// 获取文件流
						const fileReader = new FileReader();
						fileReader.onload = ev => {
							try {
								const data = ev.target.result;

								const workbook = XLSX.read(data, {
									type: "binary",
									cellText: false,
									cellDates: true,
								});
								that.workbookData = workbook;
								that.sheets = workbook.Workbook.Sheets;
								that.selectSheet(0)
							} catch (e) {
								console.error("上传失败", e)
							}
						}
						const blob = new Blob([res.tempFiles[0]]);
						fileReader.readAsBinaryString(blob);

					}
				});
				// #endif
				// #ifdef APP
				if (this._size >= this.count) {
					console.log(`只允许上传${this.count}个文件`)
					return;
				}

				// #endif
			},
			// 查询sheet数据
			selectSheet(i) {
				if (!this.showTable) {
					this.showTable = true;
				}
				this.sheetIndex = i;
				let key = this.sheets[i].name;
				//循环读取每个文件
				const header = XLSX.utils.sheet_to_json(this.workbookData.Sheets[key], {
					/** 
					 * 当header 为1时，输出为一个二维数组，输出了所有数据，包含了空值项，但每行末尾空值不显示。
					 * 当header不为1时，输出一个包含字符串的数组，不包含空值项，直接跳过空值。同时是一个以第一行为Key值的键值对。
					 * */
					header: 1, 
					
					// 可选的选项
					// 	/** Output format */
					// 	header?: "A"|number|string[];
					
					// 	/** Override worksheet range */
					// 	range?: any;
					
					// 	/** Include or omit blank lines in the output */
					// 	blankrows?: boolean;
					
					// 	/** Default value for null/undefined values */
					// 	defval?: any;
					
					// 	/** if true, return raw data; if false, return formatted text */
					// 	raw?: boolean;
					
					// 	/** if true, skip hidden rows and columns */
					// 	skipHidden?: boolean;
					
					// 	/** if true, return raw numbers; if false, return formatted numbers */
					// 	rawNumbers?: boolean;
				});
				const sheetArray = XLSX.utils.sheet_to_json(
					this.workbookData.Sheets[key],
					// 配置单元的数据转换方法，dateNF不生效
					{
						raw: true,
						cellDates: true,
						dateNF: "yyyy/mm/dd"
					}
				);

				//若当前sheet没有数据，则continue
				if (sheetArray.length == 0) {
					this.tableList = []
					return;
				}
				this.tableTitles = header[0];
				this.handleNetX(sheetArray, header[0]);
			},
			// 数据处理
			handleNetX(sheetArray, header) {
				const totalTable = [];
				for (let index in sheetArray) {
					let row = {};
					header.map(key => {
						if (typeof sheetArray[index][key] === "object") {
							row[key] = this.handleExcelDate(sheetArray[index][key]);
						} else {
							row[key] = sheetArray[index][key];
						}
					});
					totalTable.push(row);
				}
				this.tableList = totalTable;
			},
			// 日期格式化
			handleExcelDate(date) {
				if (!date) {
					return;
				}
				// return new Date(date.getTime()).format('YYYY-MM-DD');
				return this.timestampToDate(date.getTime());
			},
			timestampToDate(timestamp) {
			  const date = new Date(timestamp + 86400);
			  const year = date.getFullYear();
			  // 月份从0开始，所以需要加1
			  const month = date.getMonth() + 1; 
			  const day = date.getDate();
			 
			  // 格式化月份和日期，保证它们至少有两位数字
			  const formattedMonth = month < 10 ? '0' + month : month;
			  const formattedDay = day < 10 ? '0' + day : day;
			 
			  return `${year}-${formattedMonth}-${formattedDay}`;
			}
		}
	}
</script>
<style lang="scss">
	.upload-bg {
		background-color: rgba(38, 82, 228, 0.07);
		// width: 260rpx;
		// height: 260rpx;
		display: flex;
		flex-direction: column;
		justify-content: center !important;
		align-items: center !important;
		
		margin: 20px;
		padding: 20px;
		border-radius: 10px;
	}

	.sheet {
		display: flex;
		flex-direction: row;
		padding: 20rpx;
	}

	.tab {
		border: 2rpx solid #007aff;
		color: #007aff;
		box-sizing: border-box;
		padding: 0 16rpx;
		margin-right: 20rpx;
		border-radius: 50rpx;
		line-height: 50rpx;

		&-selected {
			background-color: #007aff;
			color: #ffffff;
		}
	}
</style>